﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Rubik.Base;
using Rubik.Common;

namespace Rubik.Tester
{
    public class RubikSolutionTester
    {
        private static void CompareResults(byte[][,] source, byte[][,] target)
        {
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < Cube.Scale; j++)
                {
                    for (int k = 0; k < Cube.Scale; k++)
                    {
                        if (source[i][j, k] != target[i][j, k])
                        {
                            throw new Exception("The restored cube state is different for the original state");
                        }
                    }
                }
            }
        }

        private static void CheckValue(string value)
        {
            foreach (char bitValue in value)
            {
                if (bitValue != '1' && bitValue != '0')
                {
                    throw new Exception("Invalid result value. The result should contain only '0' and '1'");
                }
            }
        }

        /// <summary>
        /// Tests the specified cube serializer.
        /// </summary>
        /// <param name="activator">The activator.</param>
        /// <param name="cube">The cube.</param>
        /// <returns>The test result.</returns>
        public SolutionTestResult Test(RubikSolutionActivator activator, Cube cube)
        {
            string errorMessage = String.Empty;
            string value = String.Empty;
            byte[][,] restoredState = null;
            bool isPassed;

            byte[][,] originalState = cube.Dump();

            try
            {
                // TODO: use separated domain to avoid cheating.
                ICubeSerializer cubeSerializer = activator.CreaterInstance();
                value = cubeSerializer.Serialize(originalState);

                CheckValue(value);
                cubeSerializer = activator.CreaterInstance();
                restoredState = cubeSerializer.Deserialize(value);

                CompareResults(originalState, restoredState);
                isPassed = true;
            }
            catch(Exception ex)
            {
                isPassed = false;
                errorMessage = ex.Message;
            }
            return new SolutionTestResult(isPassed,
                value.Length,
                value,
                originalState,
                restoredState,
                errorMessage);
        }
    }
}
